import { buffer, stream, util } from "@kit.ArkTS";
import hilog from "@ohos.hilog";

export const waitFor=(millSeconds:number):Promise<void>=>new Promise((r,_)=>{
  setTimeout(()=>{
    r()
  },millSeconds)
})

export class StringStream extends stream.Readable{
  constructor(private dataSize: number,private chunkSize: number) {
    super();
  }
  doRead(size: number): void {
    if (this.dataSize>0) {
      this.push("a".repeat(this.chunkSize))
      this.dataSize -= this.chunkSize;
    }else{
      this.push(null)
    }
  }
}
export function stringStream(size: number, chunkSize: number): stream.Readable {
  return new StringStream(size,chunkSize)
}
export class ByteStream extends stream.Readable{
  constructor(private dataSize: number,private chunkSize: number) {
    super();
  }
  doRead(size: number): void {
    if (this.dataSize>0) {
      this.push(new Uint8Array(this.chunkSize))
      this.dataSize -= this.chunkSize;
    }else{
      this.push(null)
    }
  }
}
export function byteStream(size: number, chunkSize: number): stream.Readable {
  return new ByteStream(size,chunkSize)
}

export class PatternedByteStream extends stream.Readable{
  private dataCursor = 0;
  constructor(private dataSize: number,private chunkSize: number,private  data:number[]) {
    super();
  }
  doRead(size: number): void {
    if (this.dataSize>0) {
      const z = Math.min(this.dataSize, this.chunkSize);
      const bytes = new Uint8Array(this.data.slice(this.dataCursor, this.dataCursor + z));
      this.dataSize -= z;
      this.dataCursor += z;

      const result = this.push( bytes);
    }else{
      this.push(null)
    }
  }
}
export function patternedByteStream(size: number, chunkSize: number) {
  let n = 0;
  const data = Array<number>(size);
  for (let i = 0; i < size; ++i) {
    data[i] = n++ % 128;
  }
  return {
    stream: new PatternedByteStream(size,chunkSize,data),
    array: new Uint8Array(data),
  };
}

export class MockReadStream extends stream.Readable{
  constructor(private data: Uint8Array | string,private offset?: number,private  length?: number) {
    super()
  }
  doRead(size: number) {
    if (typeof this.data === 'string') {
      this.push(this.data)
    } else {
      this.push(new Uint8Array(buffer.from(this.data, this.offset, this.length).buffer))
    }
    this.push(null)
  }

}
export class MockBuffersReadStream extends stream.Readable{
  private dataCursor = 0
  constructor(private data: buffer.Buffer[]) {
    super()
  }
  doRead(size: number) {
    if (this.dataCursor<this.data.length) {
      this.push(new Uint8Array(this.data[this.dataCursor].buffer))
      this.dataCursor++
    }else{
      this.push(null)
    }
  }

}